chore: migrate httpx to httpx2 (PY-09)#38
Conversation
…t production API (#9606db) - Fix Integration crash: alias was 'type' but API returns 'channel'; rename alias to 'channel', keep Python attribute as integration_type for compat - Remove phantom active field from Integration (API never returns it) - Promote Integration fields: created_by, created_at, region, metadata - Define EscalationStep sub-model with uuid, wait_before, channels, temp_id - Promote EscalationPolicy fields: created_by, created_at, grouped_alerts_window, grouped_alerts_enabled, monitor_count; type steps as list[EscalationStep] - Add sso_picture_url to TeamMember - Export EscalationStep from hyperping.models and hyperping top-level
…ationPolicy/TeamMember (#9606db) - Sync test: use channel instead of type in Integration mocks, assert new fields - Sync test: enrich EscalationPolicy mocks with steps/createdAt/monitorCount, add EscalationStep assertions - Sync test: add ssoPictureUrl to TeamMember mock, assert sso_picture_url - Async test: mirror all sync mock updates and assertions
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Adding EscalationStep to the oncall_models import pushed the line past the 100-character limit. Split it across lines using parentheses so both E501 and I001 stay clean.
Replace httpx>=0.27,<1.0 with httpx2>=2.4,<3.0 in project dependencies. Update all four client construction sites (client.py, _async_client.py, _mcp_transport.py, _async_mcp_transport.py) to import httpx2 with an httpx alias so the rest of the code is unchanged. Since httpx2 uses httpcore2 instead of httpcore, extend respx's default HTTPCoreMocker with httpcore2 targets in conftest so @respx.mock continues to intercept test requests. Two test adjustments for type compatibility: - test_async_client.py: switch to httpx2 (no respx mock usage, direct _client.request patching); MagicMock(spec=httpx2.Response) and httpx2.ConnectError side effects now match the client exception handlers. - test_client_coverage.py: keep httpx for respx return values; replace httpx.ConnectError/TimeoutException side effects with httpcore2 equivalents so httpx2 exception mapper converts them to types the client catches.
|
Reviewer context (not a merge request): PY-09 httpx2 migration plus on-call/integration model enrichment: adds Where to focus review: Risks / verify: The CI status: No checks triggered (targets Notes: Another httpx2 migration (overlaps #39/#40/#44). Consolidate the migration into a single PR to avoid repeated lockfile churn. |
Resolves the uv.lock conflict by regenerating the lockfile against the merged pyproject (httpx2 dependency plus the hyp CLI / typer extras now on main). No source conflicts.
|
Update (conflict resolution + merge order): Merged This is the httpx2 migration base. Recommended to merge first among the migration PRs. Important: #39 and #40 each independently carry the same httpx2 swap (not stacked on this PR), so merging more than one lineage will conflict heavily. Pick one: either merge this (#38) for httpx2 alone, or merge #40 which bundles httpx2 + streaming + full OTel. Do not merge both #38 and #40. |
Summary
Migrates the project's HTTP client from httpx (0.x) to httpx2 (2.x), the successor library that Pydantic and other projects have adopted as the 2026 default. This is a mechanical dependency swap: the API surface is identical so all calling code is unchanged.
What changed
pyproject.tomlhttpx>=0.27,<1.0replaced withhttpx2>=2.4,<3.0uv.locksrc/hyperping/client.pyimport httpx2 as httpxsrc/hyperping/_async_client.pyimport httpx2 as httpxsrc/hyperping/_mcp_transport.pyimport httpx2 as httpxsrc/hyperping/_async_mcp_transport.pyimport httpx2 as httpxtests/unit/conftest.pytests/unit/test_async_client.pyimport httpx2 as httpx(no respx usage)tests/unit/test_client_coverage.pyimport httpcore2; swap side-effect exceptionsWhy this shape
httpx2 uses httpcore2 instead of httpcore internally. The test mocking library (respx) patches httpcore by default; extending its
HTTPCoreMocker.targetswith the httpcore2 equivalents in conftest is the minimal shim to keep the existing@respx.mockpattern working without rewriting tests.The alias
import httpx2 as httpxensures zero diffs in calling code: the library surface is identical so type annotations, exception catches, and client construction all remain unchanged.Verification matrix
pytest tests/unit/ --ignore=test_otel.pyruff check src/ tests/unit/mypy src/hyperping/uv sync --extra devAcceptance criteria
httpx2>=2.4,<3.0in pyproject.toml